home *** CD-ROM | disk | FTP | other *** search
/ TeX 1995 July / TeX CD-ROM July 1995 (Disc 1)(Walnut Creek)(1995).ISO / dviware / xdvi-dos / src / pk.c < prev    next >
Text File  |  1992-10-21  |  8KB  |  325 lines

  1. /***
  2.  ***    PK font reading routines.
  3.  ***    Public routines are read_PK_index and read_PK_char.
  4.  ***/
  5.  
  6. #define PK_ID      89
  7. #define PK_CMD_START 240
  8. #define PK_X1     240
  9. #define PK_X2     241
  10. #define PK_X3     242
  11. #define PK_X4     243
  12. #define PK_Y      244
  13. #define PK_POST   245
  14. #define PK_NOOP   246
  15. #define PK_PRE    247
  16.  
  17. static    int    PK_flag_byte;
  18. static    unsigned PK_input_byte;
  19. static    int    PK_bitpos;
  20. static    int    PK_dyn_f;
  21. static    int    PK_repeat_count;
  22.  
  23. static    int
  24. PK_get_nyb(fp)
  25.     register FILE *fp;
  26. {
  27.     unsigned temp;
  28.     if (PK_bitpos < 0) {
  29.         PK_input_byte = one(fp);
  30.         PK_bitpos = 4;
  31.     }
  32.     temp = PK_input_byte >> PK_bitpos;
  33.     PK_bitpos -= 4;
  34.     return (temp & 0xf);
  35. }
  36.  
  37.  
  38. static    int
  39. PK_packed_num(fp)
  40.     register FILE *fp;
  41. {
  42.     int    i,j;
  43.  
  44.     if ((i = PK_get_nyb(fp)) == 0) {
  45.         do {
  46.         j = PK_get_nyb(fp);
  47.         ++i;
  48.         }
  49.         while (j == 0);
  50.         while (i > 0) {
  51.         j = (j << 4) | PK_get_nyb(fp);
  52.         --i;
  53.         }
  54.         return (j - 15 + ((13 - PK_dyn_f) << 4) + PK_dyn_f);
  55.     }
  56.     else {
  57.         if (i <= PK_dyn_f) return i;
  58.         if (i < 14)
  59.         return (((i - PK_dyn_f - 1) << 4) + PK_get_nyb(fp)
  60.             + PK_dyn_f + 1);
  61.         if (i == 14) PK_repeat_count = PK_packed_num(fp);
  62.         else PK_repeat_count = 1;
  63.         return PK_packed_num(fp);
  64.     }
  65. }
  66.  
  67.  
  68. static    void
  69. PK_skip_specials(fontp)
  70.     register struct font *fontp;
  71. {
  72.     int i,j;
  73.     register FILE *fp = fontp->file;
  74.  
  75.     do {
  76.         PK_flag_byte = one(fp);
  77.         if (PK_flag_byte >= PK_CMD_START) {
  78.         switch (PK_flag_byte) {
  79.             case PK_X1 :
  80.             case PK_X2 :
  81.             case PK_X3 :
  82.             case PK_X4 :
  83.             i = 0;
  84.             for (j = PK_CMD_START; j <= PK_flag_byte; ++j)
  85.                 i = (i << 8) | one(fp);
  86.             while (i--) (void) one(fp);
  87.             break;
  88.             case PK_Y :
  89.             (void) four(fp);
  90.             case PK_POST :
  91.             case PK_NOOP :
  92.             break;
  93.             default :
  94.             oops("Unexpected %d in PK file %s", PK_flag_byte,
  95.                 fontp->filename);
  96.             break;
  97.         }
  98.         }
  99.     }
  100.     while (PK_flag_byte != PK_POST && PK_flag_byte >= PK_CMD_START);
  101. }
  102.  
  103. /*
  104.  *    Public routines
  105.  */
  106.  
  107. static    void
  108. read_PK_char(fontp, ch)
  109.     register struct font *fontp;
  110.     ubyte    ch;
  111. {
  112.     int    i, j;
  113.     int    n;
  114.     int    row_bit_pos;
  115.     Boolean    paint_switch;
  116.     BMUNIT    *cp;
  117.     register struct glyph *g;
  118.     register FILE *fp = fontp->file;
  119.     long    fpwidth;
  120.     BMUNIT    word;
  121.     int    word_weight, bytes_wide;
  122.     int    rows_left, h_bit, count;
  123.  
  124.     g = &fontp->glyph[ch];
  125.     PK_flag_byte = g->x2;
  126.     PK_dyn_f = PK_flag_byte >> 4;
  127.     paint_switch = ((PK_flag_byte & 8) != 0);
  128.     PK_flag_byte &= 0x7;
  129.     if (PK_flag_byte == 7) n = 4;
  130.     else if (PK_flag_byte > 3) n = 2;
  131.     else n = 1;
  132.  
  133.     if (debug & DBG_PK) Printf("loading pk char %d, char type %d ", ch, n);
  134.  
  135.     /*
  136.      * now read rest of character preamble
  137.      */
  138.     if (n != 4) fpwidth = num(fp, 3);
  139.     else {
  140.         fpwidth = sfour(fp);
  141.         (void) four(fp);    /* horizontal escapement */
  142.     }
  143.     (void) num(fp, n);    /* vertical escapement */
  144.     {
  145.         unsigned long w, h;
  146.  
  147.         w = num(fp, n);
  148.         h = num(fp, n);
  149.         if (w > 0x7fff || h > 0x7fff)
  150.         oops("Character %d too large in file %s", ch, fontp->fontname);
  151.         g->bitmap.w = w;
  152.         g->bitmap.h = h;
  153.     }
  154.     g->x = snum(fp, n);
  155.     g->y = snum(fp, n);
  156.  
  157.     g->dvi_adv = fontp->dimconv * fpwidth;
  158.  
  159.     if (debug & DBG_PK) {
  160.         if (g->bitmap.w != 0)
  161.         Printf(", size=%dx%d, dvi_adv=%ld", g->bitmap.w, g->bitmap.h,
  162.             g->dvi_adv);
  163.         Putchar('\n');
  164.     }
  165.  
  166.     alloc_bitmap(&g->bitmap);
  167.     cp = (BMUNIT *) g->bitmap.bits;
  168.  
  169.     /*
  170.      * read character data into *cp
  171.      */
  172.     bytes_wide = ROUNDUP(g->bitmap.w, BITS_PER_BMUNIT) * BYTES_PER_BMUNIT;
  173.     PK_bitpos = -1;
  174.     if (PK_dyn_f == 14) {    /* get raster by bits */
  175.         bzero(g->bitmap.bits, g->bitmap.h * bytes_wide);
  176.         for (i = 0; i < g->bitmap.h; i++) {    /* get all rows */
  177.         cp = ADD(g->bitmap.bits, i * bytes_wide);
  178. #ifndef    MSBITFIRST
  179.         row_bit_pos = -1;
  180. #else
  181.         row_bit_pos = BITS_PER_BMUNIT;
  182. #endif
  183.         for (j = 0; j < g->bitmap.w; j++) {    /* get one row */
  184.             if (--PK_bitpos < 0) {
  185.             word = one(fp);
  186.             PK_bitpos = 7;
  187.             }
  188. #ifndef    MSBITFIRST
  189.             if (++row_bit_pos >= BITS_PER_BMUNIT) {
  190.             cp++;
  191.             row_bit_pos = 0;
  192.             }
  193. #else
  194.             if (--row_bit_pos < 0) {
  195.             cp++;
  196.             row_bit_pos = BITS_PER_BMUNIT - 1;
  197.             }
  198. #endif
  199.             if (word & (1 << PK_bitpos)) *cp |= 1 << row_bit_pos;
  200.         }
  201.         }
  202.     }
  203.     else {        /* get packed raster */
  204.         rows_left = g->bitmap.h;
  205.         h_bit = g->bitmap.w;
  206.         PK_repeat_count = 0;
  207.         word_weight = BITS_PER_BMUNIT;
  208.         word = 0;
  209.         while (rows_left > 0) {
  210.         count = PK_packed_num(fp);
  211.         while (count > 0) {
  212.             if (count < word_weight && count < h_bit) {
  213. #ifndef    MSBITFIRST
  214.             if (paint_switch)
  215.                 word |= bit_masks[count] <<
  216.                 (BITS_PER_BMUNIT - word_weight);
  217. #endif
  218.             h_bit -= count;
  219.             word_weight -= count;
  220. #ifdef    MSBITFIRST
  221.             if (paint_switch)
  222.                 word |= bit_masks[count] << word_weight;
  223. #endif
  224.             count = 0;
  225.             }
  226.             else if (count >= h_bit && h_bit <= word_weight) {
  227.             if (paint_switch)
  228.                 word |= bit_masks[h_bit] <<
  229. #ifndef    MSBITFIRST
  230.                 (BITS_PER_BMUNIT - word_weight);
  231. #else
  232.                 (word_weight - h_bit);
  233. #endif
  234.             *cp++ = word;
  235.             /* "output" row(s) */
  236.             for (i = PK_repeat_count * bytes_wide /
  237.                 BYTES_PER_BMUNIT; i > 0; --i) {
  238.                 *cp = *SUB(cp, bytes_wide);
  239.                 ++cp;
  240.             }
  241.             rows_left -= PK_repeat_count + 1;
  242.             PK_repeat_count = 0;
  243.             word = 0;
  244.             word_weight = BITS_PER_BMUNIT;
  245.             count -= h_bit;
  246.             h_bit = g->bitmap.w;
  247.             }
  248.             else {
  249.             if (paint_switch)
  250. #ifndef    MSBITFIRST
  251.                 word |= bit_masks[word_weight] <<
  252.                 (BITS_PER_BMUNIT - word_weight);
  253. #else
  254.                 word |= bit_masks[word_weight];
  255. #endif
  256.             *cp++ = word;
  257.             word = 0;
  258.             count -= word_weight;
  259.             h_bit -= word_weight;
  260.             word_weight = BITS_PER_BMUNIT;
  261.             }
  262.         }
  263.         paint_switch = 1 - paint_switch;
  264.         }
  265.         if (cp != ((BMUNIT *) (g->bitmap.bits + bytes_wide * g->bitmap.h)))
  266.         oops("Wrong number of bits stored:  char. %d, font %s", ch,
  267.             fontp->fontname);
  268.         if (rows_left != 0 || h_bit != g->bitmap.w)
  269.         oops("Bad pk file (%s), too many bits", fontp->fontname);
  270.     }
  271. }
  272.  
  273. void
  274. read_PK_index(fontp)
  275.     register struct font *fontp;
  276. {
  277.     int    hppp, vppp;
  278.  
  279.     fontp->read_char = read_PK_char;
  280.     if (debug & DBG_PK)
  281.         Printf("Reading PK pixel file %s\n", fontp->filename);
  282.  
  283.     Fseek(fontp->file, (long) one(fontp->file), 1);    /* skip comment */
  284.  
  285.     (void) four(fontp->file);        /* skip design size */
  286.     (void) four(fontp->file);        /* skip checksum */
  287.     hppp = sfour(fontp->file);
  288.     vppp = sfour(fontp->file);
  289.     if (hppp != vppp && (debug & DBG_PK))
  290.         Printf("Font has non-square aspect ratio %d:%d\n", vppp, hppp);
  291.     /*
  292.      * Prepare glyph array.
  293.      */
  294.     fontp->glyph = (struct glyph *) xmalloc(256 * sizeof(struct glyph),
  295.         "glyph array");
  296.     bzero((char *) fontp->glyph, 256 * sizeof(struct glyph));
  297.     /*
  298.      * Read glyph directory (really a whole pass over the file).
  299.      */
  300.     for (;;) {
  301.         int bytes_left, flag_low_bits;
  302.         unsigned int ch;
  303.  
  304.         PK_skip_specials(fontp);
  305.         if (PK_flag_byte == PK_POST) break;
  306.         flag_low_bits = PK_flag_byte & 0x7;
  307.         if (flag_low_bits == 7) {
  308.         bytes_left = four(fontp->file);
  309.         ch = four(fontp->file);
  310.         } else if (flag_low_bits > 3) {
  311.         bytes_left = ((flag_low_bits - 4) << 16) + two(fontp->file);
  312.         ch = one(fontp->file);
  313.         } else {
  314.         bytes_left = (flag_low_bits << 8) + one(fontp->file);
  315.         ch = one(fontp->file);
  316.         }
  317.         fontp->glyph[ch].addr = ftell(fontp->file);
  318.         fontp->glyph[ch].x2 = PK_flag_byte;
  319.         Fseek(fontp->file, (long) bytes_left, 1);
  320.         if (debug & DBG_PK)
  321.         Printf("Scanning pk char %u, at %ld.\n", ch,
  322.             fontp->glyph[ch].addr);
  323.     }
  324. }
  325.